/**
* @file drv_qspi.c
* @brief  qspi驱动
* @details 
* @author huangbin
* @version V1.0.0
* @date 2025-07-13
* @copyright All documents are copyrighted by Shenzhen Xinlongwei Technology Co., LTD.
*            They may not be used for commercial purposes without permission
*/
#include "inc.h"
#include "drv_qspi.h"
QSPI_ComConfig_InitTypeDef  QSPI_ComConfig_InitStructure;

void QSPI_GPIO_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	
	RCC_APB2PeriphClockCmd(QSPIx_CLK_GPIO_CLK | QSPIx_BANK1_CS_GPIO_CLK | QSPIx_BANK1_D0_GPIO_CLK | \
		QSPIx_BANK1_D1_GPIO_CLK | QSPIx_BANK1_D2_GPIO_CLK | QSPIx_BANK1_D3_GPIO_CLK | RCC_APB2Periph_AFIO, ENABLE);
	
	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
	
	GPIO_PinRemapConfig(GPIO_Remap_QSPI_AF2, ENABLE);
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

	GPIO_InitStructure.GPIO_Pin = QSPIx_CLK_PIN;
	GPIO_Init(QSPIx_CLK_GPIO_PORT, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = QSPIx_BANK1_D0_PIN;
	GPIO_Init(QSPIx_BANK1_D0_GPIO_PORT, &GPIO_InitStructure);  

	GPIO_InitStructure.GPIO_Pin = QSPIx_BANK1_D1_PIN;
	GPIO_Init(QSPIx_BANK1_D1_GPIO_PORT, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = QSPIx_BANK1_D2_PIN;
	GPIO_Init(QSPIx_BANK1_D2_GPIO_PORT, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = QSPIx_BANK1_D3_PIN;
	GPIO_Init(QSPIx_BANK1_D3_GPIO_PORT, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = QSPIx_BANK1_CS_PIN;
	GPIO_Init(QSPIx_BANK1_CS_GPIO_PORT, &GPIO_InitStructure);
}
//DMA config: qspi to memory
void QSPI_DMA_Config(void)
{
	DMA_InitTypeDef DMA_InitStructure;
	
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
	
	DMA_StructInit(&DMA_InitStructure);
	
	DMA_InitStructure.DMA_PeripheralBaseAddr	= (uint32_t) & QUADSPI->DR ;
	DMA_InitStructure.DMA_MemoryBaseAddr		= 0;	
	DMA_InitStructure.DMA_DIR					= DMA_DIR_PeripheralDST;
	DMA_InitStructure.DMA_PeripheralDataSize	= DMA_PeripheralDataSize_Byte;
	DMA_InitStructure.DMA_MemoryDataSize		= DMA_MemoryDataSize_Byte;
	DMA_InitStructure.DMA_PeripheralInc			= DMA_PeripheralInc_Disable;
	DMA_InitStructure.DMA_MemoryInc				= DMA_MemoryInc_Enable;
	DMA_InitStructure.DMA_Mode					= DMA_Mode_Normal;
	DMA_InitStructure.DMA_BufferSize			= 0;
	DMA_InitStructure.DMA_Priority				= DMA_Priority_Low;
	DMA_InitStructure.DMA_M2M                   = DMA_M2M_Disable;
	DMA_Init(QSPI_DMA_CHANNEL, &DMA_InitStructure);
}
//DMA config:  memory to memory with bytes
void QSPI_M2M_DMA_Config(void)
{
	DMA_InitTypeDef DMA_InitStructure;
	
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
	
	DMA_StructInit(&DMA_InitStructure);
	DMA_DeInit(QSPI_M2M_DMA_CHANNEL);	
	
	DMA_InitStructure.DMA_PeripheralBaseAddr	= 0;
	DMA_InitStructure.DMA_MemoryBaseAddr		= 0;	
	DMA_InitStructure.DMA_DIR					= DMA_DIR_PeripheralSRC;
	DMA_InitStructure.DMA_PeripheralDataSize	= DMA_PeripheralDataSize_Byte;
	DMA_InitStructure.DMA_MemoryDataSize		= DMA_MemoryDataSize_Byte;
	DMA_InitStructure.DMA_PeripheralInc			= DMA_PeripheralInc_Enable;
	DMA_InitStructure.DMA_MemoryInc				= DMA_MemoryInc_Enable;
	DMA_InitStructure.DMA_Mode					= DMA_Mode_Normal;
	DMA_InitStructure.DMA_BufferSize			= 0;
	DMA_InitStructure.DMA_Priority				= DMA_Priority_Low;
	DMA_InitStructure.DMA_M2M                   = DMA_M2M_Enable;
	DMA_Init(QSPI_M2M_DMA_CHANNEL, &DMA_InitStructure);
}
void QSPI_Configuration(void)
{
	QSPI_InitTypeDef  QSPI_InitStructure;
	NVIC_InitTypeDef NVIC_InitStruct;
	
	DebugPrintf("QSPI Init\r\n");
	QSPI_GPIO_Config();
	QSPI_DMA_Config();
	QSPI_M2M_DMA_Config();
	
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_QSPI,ENABLE);
	
	QSPI_DeInit();

	/* Initialize QuadSPI ------------------------------------------------------*/
	QSPI_StructInit(&QSPI_InitStructure);
	QSPI_InitStructure.QSPI_SShift    = QSPI_SShift_NoShift;        //采样偏移
	QSPI_InitStructure.QSPI_Prescaler = 2;			           		//QSPI 预分频器值216/3
	QSPI_InitStructure.QSPI_FSize     = 0x18;         	            //24bit 地址模式
	QSPI_InitStructure.QSPI_CKMode    = QSPI_CKMode_Mode0;         //时钟模式
	QSPI_InitStructure.QSPI_CSHTime   = QSPI_CSHTime_2Cycle;       //芯片选择高时间
	QSPI_Init(&QSPI_InitStructure);
	
//	QSPI_ITConfig(QSPI_IT_TO | QSPI_IT_SM | QSPI_IT_TC | QSPI_IT_TE,ENABLE); //TO:TimeOut,sm:状态匹配中断,TC:传输完成中断,TE:传输错误中断
	QSPI_ITConfig(QSPI_IT_TO | QSPI_IT_TC | QSPI_IT_TE,ENABLE); //TO:TimeOut,sm:状态匹配中断,TC:传输完成中断,TE:传输错误中断

	NVIC_InitStruct.NVIC_IRQChannel = QUADSPI_IRQn;
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
	NVIC_Init(&NVIC_InitStruct);

	QSPI_SetFIFOThreshold(0);
	
	QSPI_Cmd(ENABLE);

	DebugPrintf("Flash Init,QSPI_Prescaler=%d,%dMhz\r\n",QSPI_InitStructure.QSPI_Prescaler,SystemCoreClock/1000000/(QSPI_InitStructure.QSPI_Prescaler+1));
	
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_DHHC        = QSPI_ComConfig_DHHC_Enable;//DDR模式下数据输出延时使能
	QSPI_ComConfig_InitStructure.QSPI_ComConfig_SIOOMode    = QSPI_ComConfig_SIOOMode_Disable;//仅发送一次指令模块使能
}
void QSPI_DMA_Send(uint8_t *buf,uint16_t len)
{
	DMA_Cmd(QSPI_DMA_CHANNEL,DISABLE);
	DMA_SetCurrDataCounter(QSPI_DMA_CHANNEL,len);
	QSPI_DMA_CHANNEL->CCR = (QSPI_DMA_CHANNEL->CCR & ~DMA_CCR1_DIR) | DMA_DIR_PeripheralDST;
	QSPI_DMA_CHANNEL->CMAR = (uint32_t)buf;
	DMA_Cmd(QSPI_DMA_CHANNEL,ENABLE);
	QSPI_DMACmd(ENABLE);
}

void QSPI_DMA_Recv(uint8_t *buf,uint16_t len)
{
	DMA_Cmd(QSPI_DMA_CHANNEL,DISABLE);
	DMA_SetCurrDataCounter(QSPI_DMA_CHANNEL,len);
	QSPI_DMA_CHANNEL->CCR = (QSPI_DMA_CHANNEL->CCR & ~DMA_CCR1_DIR) | DMA_DIR_PeripheralSRC;
	QSPI_DMA_CHANNEL->CMAR = (uint32_t)buf;
	DMA_Cmd(QSPI_DMA_CHANNEL,ENABLE);
	QSPI_DMACmd(ENABLE);
}
volatile uint32_t QSPI_SR_FLAG;
void QUADSPI_IRQHandler(void)
{
	if(QSPI_GetITStatus(QSPI_IT_TO))
	{
		QSPI_ClearITPendingBit(QSPI_IT_TO);
		QSPI_SR_FLAG |= QUADSPI_SR_TOF;
	}
	if(QSPI_GetITStatus(QSPI_IT_SM))
	{
		QSPI_ClearITPendingBit(QSPI_IT_SM);
		QSPI_SR_FLAG |= QUADSPI_SR_SMF;
	}
	if(QSPI_GetITStatus(QSPI_IT_FT)) //FIFO 阈值中断
	{
//		if(qspi_trans.state == 1)
//		{
//			QSPI_SendData32(*(uint32_t *)&qspi_trans.buf[qspi_trans.buf_pos]);
//			qspi_trans.buf_pos += 4;
//		}
//		else if(qspi_trans.state == 2)
//		{
//			*(uint32_t *)&(qspi_trans.buf[qspi_trans.buf_pos]) = QSPI_ReceiveData32();
//			qspi_trans.buf_pos += 4;
//		}
//		if(qspi_trans.buf_pos >= qspi_trans.buf_len)
//		{
//			QSPI_ITConfig(QSPI_IT_FT, DISABLE);
//		}
	}
	if(QSPI_GetITStatus(QSPI_IT_TC))
	{
		QSPI_ClearITPendingBit(QSPI_IT_TC);
		QSPI_SR_FLAG |= QUADSPI_SR_TCF;
	}
	if(QSPI_GetITStatus(QSPI_IT_TE))
	{
		QSPI_ClearITPendingBit(QSPI_IT_TE);
		QSPI_SR_FLAG |= QUADSPI_SR_TEF;
	}
}
/************************END OF FILE*********************************************/

